package jgcp.client;

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import java.io.File;
import java.net.Socket;
import java.util.regex.Matcher;

import jgcp.common.Task;
import jgcp.common.TaskDescription;
import jgcp.common.TaskType;
import jgcp.common.network.Connection;
import jgcp.common.network.FileSender;
import jgcp.config.Configuration;
import jgcp.message.Message;
import jgcp.message.MessageType;
import jgcp.utils.Packer;

/**
 * 
 * @Date 31/05/2009
 * @author Joko
 * @version 1.0
 */

public class GuiClient {

	private JFrame frame;

	private final JTabbedPane tabbedPane = new JTabbedPane();
	private final JTextPane javaGridComputingTextPane = new JTextPane();
	private final JPanel panel = new JPanel();
	private final JPanel panel_1 = new JPanel();
	private final JPanel panel_2 = new JPanel();
	private final JTextPane serverIpAddressTextPane = new JTextPane();
	private final JTextPane loginTextPane = new JTextPane();
	private final JTextField serverIPAddrtxtField = new JTextField();
	private final JTextPane userNameTextPane = new JTextPane();
	private final JTextField userNameTxtField = new JTextField();
	private final JTextPane passwordTextPane = new JTextPane();
	private final JPasswordField passwordField = new JPasswordField();
	private final JButton connectButton = new JButton();
	private final JTextPane inputAppFileTextPane = new JTextPane();
	private final JTextPane schedulingAlgorithmTextPane = new JTextPane();
	private final JTextPane budgetTextPane = new JTextPane();
	private final JTextField inputAppFileTextField = new JTextField();
	private final JButton browseAButton = new JButton();
	private final JComboBox schedulingAlgorithmComboBox = new JComboBox();
	private final JTextField budgetTextField = new JTextField();
	private final JTextPane resultDataFileTextPane_1 = new JTextPane();
	private final JButton computeButton = new JButton();
	private final JTextPane inputDataFileTextPane = new JTextPane();
	private final JTextField inputDataFileTextField = new JTextField();
	private final JButton browseBButton = new JButton();
	private final JTextPane budgetTextPane_1 = new JTextPane();
	private final JTextPane serverIpAddressTextPane_1 = new JTextPane();
	private final JTextField portIPAddrtxtField = new JTextField();
	private final JTextPane connectToTextPane = new JTextPane();
	private final JTextPane connectTo = new JTextPane();
	private final JPanel panel_4 = new JPanel();
	private final JTextPane resultDataFileTextPane = new JTextPane();
	private final JTextField resultFile = new JTextField();
	private final JButton browseCButton = new JButton();
	private final JButton saveButton = new JButton();
	private final JTextArea workerList = new JTextArea();
	private final JButton refreshButton = new JButton();

	private final JTextArea taskList = new JTextArea();
	private final JButton refreshButton_1 = new JButton();
	private final JLabel taskidLabel = new JLabel();
	private final JTextArea taskid = new JTextArea();

	private final JButton cancelButton = new JButton();
	private final JButton queryButton = new JButton();
	/**
	 * Launch the application
	 * 
	 * @param args
	 */
	public static void main(String args[]) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					GuiClient window = new GuiClient();
					window.frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the application
	 */
	public GuiClient() {
		jbInit();
	}

	/**
	 * Initialize the contents of the frame
	 */
	private void jbInit() {
		frame = new JFrame();
		frame.setTitle("JGCP Client V 1.0");
		frame.getContentPane().setLayout(null);
		frame.setBounds(100, 100, 812, 509);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		frame.getContentPane().add(tabbedPane);
		tabbedPane.setBounds(10, 54, 784, 410);

		tabbedPane.addTab("Connection", null, panel, null);
		panel.setLayout(null);

		panel.add(serverIpAddressTextPane);
		serverIpAddressTextPane.setBounds(195, 125, 90, 22);
		serverIpAddressTextPane.setText("Server Address");
		serverIpAddressTextPane.setOpaque(false);

		panel.add(loginTextPane);
		loginTextPane.setBounds(350, 75, 55, 30);
		loginTextPane.setText("Login");
		loginTextPane.setOpaque(false);
		loginTextPane.setFont(new Font("Dialog", Font.BOLD, 18));
		loginTextPane.setFocusable(false);

		panel.add(serverIPAddrtxtField);
		serverIPAddrtxtField.setBounds(303, 125, 243, 20);

		panel.add(connectButton);
		connectButton.addActionListener(new ConnectButtonActionListener());
		connectButton.setBounds(338, 255, 81, 26);
		connectButton.setText("Connect");

		panel.add(userNameTextPane);
		userNameTextPane.setBounds(195, 180, 70, 22);
		userNameTextPane.setText("User Name");
		userNameTextPane.setOpaque(false);

		panel.add(userNameTxtField);
		userNameTxtField.setBounds(303, 182, 243, 20);

		panel.add(passwordTextPane);
		passwordTextPane.setBounds(195, 209, 62, 22);
		passwordTextPane.setText("Password");
		passwordTextPane.setOpaque(false);

		panel.add(passwordField);
		passwordField.setBounds(303, 212, 243, 20);

		tabbedPane.addTab("Job Setting", null, panel_2, null);
		panel_2.setLayout(null);

		panel_2.add(inputAppFileTextPane);
		inputAppFileTextPane.setFocusable(false);
		inputAppFileTextPane.setBounds(21, 37, 123, 22);
		inputAppFileTextPane.setText("Input Application File");
		inputAppFileTextPane.setOpaque(false);

		panel_2.add(schedulingAlgorithmTextPane);
		schedulingAlgorithmTextPane.setFocusable(false);
		schedulingAlgorithmTextPane.setBounds(20, 95, 123, 22);
		schedulingAlgorithmTextPane.setText("Scheduling Algorithm");
		schedulingAlgorithmTextPane.setOpaque(false);

		panel_2.add(budgetTextPane);
		budgetTextPane.setFocusable(false);
		budgetTextPane.setBounds(20, 123, 45, 22);
		budgetTextPane.setText("Budget");
		budgetTextPane.setOpaque(false);

		panel_2.add(inputAppFileTextField);
		inputAppFileTextField.setBounds(153, 39, 470, 20);

		panel_2.add(browseAButton);
		browseAButton.addActionListener(new BrowseAButtonActionListener());
		browseAButton.setBounds(630, 39, 106, 20);
		browseAButton.setText("Browse..");

		panel_2.add(schedulingAlgorithmComboBox);
		schedulingAlgorithmComboBox.setBounds(152, 95, 307, 20);
		schedulingAlgorithmComboBox.setModel(new DefaultComboBoxModel(
				new String[] { "", "FCFS", "Round Robin",
						"Earliest Deadline First",
						"Earliest Deadline Constrained by Budget" }));

		panel_2.add(budgetTextField);
		budgetTextField.setBounds(152, 123, 157, 20);

		panel_2.add(resultDataFileTextPane_1);
		resultDataFileTextPane_1.setBounds(21, 177, 94, 22);
		resultDataFileTextPane_1.setOpaque(false);

		panel_2.add(computeButton);
		computeButton.addActionListener(new ComputeButtonActionListener());
		computeButton.setText("Compute");
		computeButton.setBounds(343, 209, 106, 26);

		panel_2.add(inputDataFileTextPane);
		inputDataFileTextPane.setFocusable(false);
		inputDataFileTextPane.setText("Input Data File");
		inputDataFileTextPane.setOpaque(false);
		inputDataFileTextPane.setBounds(21, 65, 85, 22);

		panel_2.add(inputDataFileTextField);
		inputDataFileTextField.setBounds(153, 67, 470, 20);

		panel_2.add(browseBButton);
		browseBButton.addActionListener(new BrowseBButtonActionListener());
		browseBButton.setText("Browse..");
		browseBButton.setBounds(630, 67, 106, 20);

		panel_2.add(budgetTextPane_1);
		budgetTextPane_1.setFocusable(false);
		budgetTextPane_1.setText("$ Grid");
		budgetTextPane_1.setOpaque(false);
		budgetTextPane_1.setBounds(315, 123, 45, 22);

		frame.getContentPane().add(javaGridComputingTextPane);
		tabbedPane.addTab("Worker", null, panel_1, null);
		panel_1.setLayout(null);

		panel_1.add(connectToTextPane);
		connectToTextPane.setText("Connect to:");
		connectToTextPane.setOpaque(false);
		connectToTextPane.setBounds(10, 15, 68, 22);

		panel_1.add(connectTo);
		connectTo.setText("xxx.xxx.au");
		connectTo.setOpaque(false);
		connectTo.setBounds(85, 15, 68, 22);

		panel_1.add(workerList);
		workerList.setBounds(50, 60, 680, 290);

		panel_1.add(refreshButton);
		refreshButton.addActionListener(new RefreshButtonActionListener());
		refreshButton.setText("Refresh");
		refreshButton.setBounds(617, 15, 106, 26);

		javaGridComputingTextPane.setFocusable(false);
		javaGridComputingTextPane.setFont(new Font("", Font.BOLD, 18));
		javaGridComputingTextPane.setOpaque(false);
		javaGridComputingTextPane
				.setText("Java Grid Computing Platform Client");
		javaGridComputingTextPane.setBounds(245, 10, 325, 38);

		panel.add(serverIpAddressTextPane_1);
		serverIpAddressTextPane_1.setText("Port");
		serverIpAddressTextPane_1.setOpaque(false);
		serverIpAddressTextPane_1.setBounds(300, 155, 28, 22);

		panel.add(portIPAddrtxtField);
		portIPAddrtxtField.setBounds(340, 155, 121, 20);

		tabbedPane.addTab("Get Result", null, panel_4, null);
		panel_4.setLayout(null);

		panel_4.add(resultDataFileTextPane);
		resultDataFileTextPane.setBounds(45, 248, 94, 22);
		resultDataFileTextPane.setText("Result Data File");
		resultDataFileTextPane.setOpaque(false);
		resultDataFileTextPane.setFocusable(false);

		panel_4.add(resultFile);
		resultFile.setBounds(145, 248, 475, 20);

		panel_4.add(browseCButton);
		browseCButton.addActionListener(new BrowseCButtonActionListener());
		browseCButton.setBounds(626, 245, 84, 26);
		browseCButton.setText("Browse..");

		panel_4.add(saveButton);
		saveButton.addActionListener(new SaveButtonActionListener());
		saveButton.setText("Save");
		saveButton.setBounds(276, 301, 106, 26);

		panel_4.add(taskList);
		taskList.setEditable(false);
		taskList.setBounds(45, 28, 486, 94);

		panel_4.add(refreshButton_1);
		refreshButton_1.addActionListener(new RefreshButton_1ActionListener());
		refreshButton_1.setText("Refresh");
		refreshButton_1.setBounds(45, 131, 106, 26);

		panel_4.add(taskidLabel);
		taskidLabel.setText("TaskId:");
		taskidLabel.setBounds(45, 221, 66, 16);

		panel_4.add(taskid);
		taskid.setBounds(145, 221, 81, 16);
		
		panel_4.add(cancelButton);
		cancelButton.addActionListener(new CancelButtonActionListener());
		cancelButton.setText("Cancel");
		cancelButton.setBounds(390, 216, 106, 26);
		
		panel_4.add(queryButton);
		queryButton.addActionListener(new QueryButtonActionListener());
		queryButton.setText("Query");
		queryButton.setBounds(276, 216, 106, 26);
		tabbedPane.setEnabledAt(1, false);
		tabbedPane.setEnabledAt(2, false);
		tabbedPane.setEnabledAt(3, false);
		
		serverIPAddrtxtField.setText("localhost");
		portIPAddrtxtField.setText("2345");
		userNameTxtField.setText("admin");
		passwordField.setText("admin");
	}

	private class ComputeButtonActionListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			try {
				computeButton_actionPerformed(e);
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		}
	}

	private class ConnectButtonActionListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			try {
				connectButton_actionPerformed(e);
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		}
	}

	private class BrowseAButtonActionListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			browseAButton_actionPerformed(e);
		}
	}

	private class BrowseBButtonActionListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			browseBButton_actionPerformed(e);
		}
	}

	private class BrowseCButtonActionListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			browseCButton_actionPerformed(e);
		}
	}

	private class RefreshButtonActionListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			try {
				refreshButton_actionPerformed(e);
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		}
	}

	private class RefreshButton_1ActionListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			refreshButton_1_actionPerformed(e);
		}
	}

	private class SaveButtonActionListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			saveButton_actionPerformed(e);
		}
	}
	private class QueryButtonActionListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			queryButton_actionPerformed(e);
		}
	}
	private class CancelButtonActionListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			cancelButton_actionPerformed(e);
		}
	}

	protected void computeButton_actionPerformed(ActionEvent e)
			throws Exception {
		if (inputAppFileTextField.getText() != "") {
			String[] buf = new String[3];
			buf[1] = inputAppFileTextField.getText();
			buf[2] = inputDataFileTextField.getText();

			if (isConnected) {
				String filename = "" + System.currentTimeMillis() + ".zip";
				String workingFolder = Configuration.getInstance()
						.getClientTempfolder();
				TaskDescription td = new TaskDescription();
				Task t = new Task();
				t.setDescription(td);
				if (buf.length >= 2) // exe|jar only
				{
					if (buf[1].endsWith("exe")) {
						td.setType(TaskType.EXE);
					} else if (buf[1].endsWith("jar")) {
						td.setType(TaskType.JAR);
					}
					td.setExefile(buf[1]);
					if (buf.length == 3) {
						td.setDataFile(buf[2]);
					}
				} else {
					return;
				}
				String file = workingFolder + filename;
				Packer.packTask(t, file);
				FileSender<TaskDescription> sender = new FileSender<TaskDescription>(
						td, file);
				int port = sender.getPort();
				sender.start();
				Message m = new Message();
				m.setType(MessageType.SUBMITTASK);
				m.setMessageBody("" + port);
				connection.writeData(m.toByteArray());
			}
			// jgcp.client.CmdClient.submitTask(buf);
		}
		;
	}

	private static Socket socket = null;
	private static Connection connection = null;
	static boolean isConnected = false;

	protected void connectButton_actionPerformed(ActionEvent e) {
		try {
			String[] buffer = new String[5];
			buffer[1] = serverIPAddrtxtField.getText();
			buffer[2] = portIPAddrtxtField.getText();
			buffer[3] = userNameTxtField.getText();
			char[] a = passwordField.getPassword();
			String b = "";
			for (int i = 0; i < a.length; i++) {
				b = b + a[i];
			}
			;
			buffer[4] = b;

			connectTo.setText(buffer[1]);
			if (!isConnected) {
				socket = new Socket(buffer[1], Integer.parseInt(buffer[2]));
				Message msg = new Message();
				msg.setType(MessageType.LOGIN);
				msg.setMessageBody(buffer[3] + " " + buffer[4]);
				socket.getOutputStream().write(msg.toByteArray());
				connection = new Connection();
				connection.setSocket(socket);
				GUiClientMessageHandler gmh = new GUiClientMessageHandler(
						connection);
				gmh.setGui(this);
				gmh.start();
			}
		} catch (Exception ee) {
		}
	}

	void enableTabs() {
		tabbedPane.setEnabledAt(1, true);
		tabbedPane.setEnabledAt(2, true);
		tabbedPane.setEnabledAt(3, true);
		tabbedPane.setSelectedIndex(1);
		inputAppFileTextField.requestFocusInWindow();
	}

	protected void browseAButton_actionPerformed(ActionEvent e) {
		inputAppFileTextField.setText(change(chooseFile(1)));
	}

	String change(String str) {
		if (str != null) {
			return str.replaceAll(Matcher.quoteReplacement("\\"), "/");
		}
		return "";
	}

	protected void browseBButton_actionPerformed(ActionEvent e) {
		inputDataFileTextField.setText(change(chooseFile(3)));
	}

	public String chooseFile(final int a) {
		JFileChooser chooser = new JFileChooser();
		chooser.setCurrentDirectory(new File("."));
		if (a == 1) {
			chooser.setFileFilter(new javax.swing.filechooser.FileFilter() {
				public boolean accept(File f) {
					return f.getName().toLowerCase().endsWith(".exe")
							|| f.getName().toLowerCase().endsWith(".jar")
							|| f.isDirectory();
				}

				public String getDescription() {
					return "Executable File/JAR File";
				}
			});
		} else if (a == 2) {
			chooser.setFileFilter(new javax.swing.filechooser.FileFilter() {
				public boolean accept(File f) {
					return f.isFile();
				}

				public String getDescription() {
					return "Data File";
				}
			});
		} else {
			chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
			chooser.setFileFilter(new javax.swing.filechooser.FileFilter() {
				public boolean accept(File f) {
					return f.isDirectory();
				}

				public String getDescription() {
					return "Folder Directory";
				}
			});
		}
		;
		String name = "";
		int r = chooser.showOpenDialog(new JFrame());
		if (r == JFileChooser.APPROVE_OPTION) {
			name = chooser.getSelectedFile().getAbsolutePath();
		}
		return name;
	}

	protected void browseCButton_actionPerformed(ActionEvent e) {
		resultFile.setText(change(chooseFile(3)));
	}

	protected void refreshButton_actionPerformed(ActionEvent e)
			throws Exception {

//		jgcp.client.CmdClient.sendMessage(MessageType.LISTWORKER);
		Message message = new Message();
		message.setType(MessageType.LISTWORKER);
		
		connection.writeData(message.toByteArray());
	}

	void setWrokers(String str)
	{
		workerList.setText(str);
	}
	protected void refreshButton_1_actionPerformed(ActionEvent e) {
		if (isConnected) {
			Message message = new Message();
			message.setType(MessageType.LISTTASKS);
			try {
				connection.writeData(message.toByteArray());
			} catch (Exception e1) {
				e1.printStackTrace();
			}
		}
	}

	void setTasklist(String str) {
		taskList.setText(str);
	}

	String getResultFile() {
		return resultFile.getText();
	}

	protected void saveButton_actionPerformed(ActionEvent e) {
		if (isConnected) {
			Message message = new Message();
			message.setType(MessageType.GETRESULT);
			message.setMessageBody(taskid.getText());
			try {
				connection.writeData(message.toByteArray());
			} catch (Exception e1) {
			}
		}
	}
	protected void queryButton_actionPerformed(ActionEvent e) {
		Message msg = new Message();
		msg.setType(MessageType.QUERYSTATUS);
		msg.setMessageBody(taskid.getText());
		try {
			connection.writeData(msg.toByteArray());
		} catch (Exception e1) {
			e1.printStackTrace();
		}
	}
	protected void cancelButton_actionPerformed(ActionEvent e) {
		Message msg = new Message();
		msg.setType(MessageType.CANCELTASK);
		msg.setMessageBody(taskid.getText());
		try {
			connection.writeData(msg.toByteArray());
		} catch (Exception e1) {
			e1.printStackTrace();
		}
	}
}
